package com.imut.lagain.controller;

import com.imut.lagain.entity.MemoryEntry;
import com.imut.lagain.service.IMemoryEntryService;
import com.imut.lagain.util.FileUtil;
import com.imut.lagain.util.JwtUtil;
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件上传控制器
 */
@RestController
@RequestMapping("/api/files")
@RequiredArgsConstructor
@Validated
public class FileController {
    private static final Logger log = LoggerFactory.getLogger(FileController.class);
    
    @Value("${file.upload.path}")
    private String uploadPath;
    
    @Value("${file.access.url}")
    private String accessUrl;
    
    private final IMemoryEntryService memoryEntryService;
    private final JwtUtil jwtUtil;
    private final FileUtil fileUtil;
    
    /**
     * 上传图片
     * @param file 图片文件
     * @param authorization JWT令牌
     * @return 上传结果
     */
    @PostMapping("/upload/image")
    public ResponseEntity<Map<String, Object>> uploadImage(
            @RequestParam("file") @NotNull MultipartFile file,
            @RequestHeader("Authorization") @NotBlank String authorization) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            String token = authorization.replace("Bearer ", "");
            if (!jwtUtil.validateToken(token)) {
                response.put("success", false);
                response.put("message", "Token无效");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }
            
            String fileUrl = fileUtil.uploadImage(file);
            
            response.put("success", true);
            response.put("fileUrl", fileUrl);
            response.put("fileSize", file.getSize());
            response.put("message", "图片上传成功");
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            log.error("Failed to upload image", e);
            response.put("success", false);
            response.put("message", "图片上传失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 上传语音
     * @param file 语音文件
     * @param authorization JWT令牌
     * @return 上传结果
     */
    @PostMapping("/upload/audio")
    public ResponseEntity<Map<String, Object>> uploadAudio(
            @RequestParam("file") @NotNull MultipartFile file,
            @RequestHeader("Authorization") @NotBlank String authorization) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            String token = authorization.replace("Bearer ", "");
            if (!jwtUtil.validateToken(token)) {
                response.put("success", false);
                response.put("message", "Token无效");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }
            
            String fileUrl = fileUtil.uploadAudio(file);
            
            response.put("success", true);
            response.put("fileUrl", fileUrl);
            response.put("fileSize", file.getSize());
            response.put("message", "语音上传成功");
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            log.error("Failed to upload audio", e);
            response.put("success", false);
            response.put("message", "语音上传失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 添加图片条目到胶囊
     * @param capsuleId 胶囊ID
     * @param authorization JWT令牌
     * @param request 添加请求
     * @return 添加结果
     */
    @PostMapping("/capsules/{capsuleId}/entries/image")
    public ResponseEntity<Map<String, Object>> addImageEntry(
            @PathVariable @Min(1) Long capsuleId,
            @RequestHeader("Authorization") @NotBlank String authorization,
            @Valid @RequestBody AddImageEntryRequest request) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            String token = authorization.replace("Bearer ", "");
            if (!jwtUtil.validateToken(token)) {
                response.put("success", false);
                response.put("message", "Token无效");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }
            
            Long userId = jwtUtil.getUserIdFromToken(token);
            
            MemoryEntry entry = memoryEntryService.createImageEntry(
                    capsuleId, request.getFileUrl(), request.getFileName(), request.getFileSize());
            
            if (entry != null) {
                response.put("success", true);
                response.put("data", entry);
                response.put("message", "图片条目添加成功");
                return ResponseEntity.ok(response);
            } else {
                response.put("success", false);
                response.put("message", "图片条目添加失败");
                return ResponseEntity.internalServerError().body(response);
            }
            
        } catch (Exception e) {
            log.error("Failed to add image entry", e);
            response.put("success", false);
            response.put("message", "添加图片条目失败");
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 添加语音条目到胶囊
     * @param capsuleId 胶囊ID
     * @param authorization JWT令牌
     * @param request 添加请求
     * @return 添加结果
     */
    @PostMapping("/capsules/{capsuleId}/entries/audio")
    public ResponseEntity<Map<String, Object>> addAudioEntry(
            @PathVariable @Min(1) Long capsuleId,
            @RequestHeader("Authorization") @NotBlank String authorization,
            @Valid @RequestBody AddAudioEntryRequest request) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            String token = authorization.replace("Bearer ", "");
            if (!jwtUtil.validateToken(token)) {
                response.put("success", false);
                response.put("message", "Token无效");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }
            
            Long userId = jwtUtil.getUserIdFromToken(token);
            
            MemoryEntry entry = memoryEntryService.createAudioEntry(
                    capsuleId, request.getFileUrl(), request.getFileName(), request.getFileSize(), request.getDuration());
            
            if (entry != null) {
                response.put("success", true);
                response.put("data", entry);
                response.put("message", "语音条目添加成功");
                return ResponseEntity.ok(response);
            } else {
                response.put("success", false);
                response.put("message", "语音条目添加失败");
                return ResponseEntity.internalServerError().body(response);
            }
            
        } catch (Exception e) {
            log.error("Failed to add audio entry", e);
            response.put("success", false);
            response.put("message", "添加语音条目失败");
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 访问文件
     * @param type 文件类型（images/audios）
     * @param filename 文件名
     * @return 文件资源
     */
    @GetMapping("/{type}/{filename:.+}")
    public ResponseEntity<Resource> getFile(@PathVariable String type, @PathVariable String filename) {
        try {
            Path filePath = Paths.get(uploadPath, type, filename);
            Resource resource = new UrlResource(filePath.toUri());
            
            if (resource.exists() && resource.isReadable()) {
                String contentType = Files.probeContentType(filePath);
                if (contentType == null) {
                    contentType = "application/octet-stream";
                }
                
                return ResponseEntity.ok()
                        .contentType(MediaType.parseMediaType(contentType))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"")
                        .body(resource);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (MalformedURLException e) {
            log.error("Failed to get file: {}", filename, e);
            return ResponseEntity.notFound().build();
        } catch (IOException e) {
            log.error("Failed to probe content type for file: {}", filename, e);
            return ResponseEntity.internalServerError().build();
        }
    }
    
    /**
     * 添加图片条目请求DTO
     */
    public static class AddImageEntryRequest {
        @NotBlank(message = "文件URL不能为空")
        @Size(max = 500, message = "文件URL长度不能超过500个字符")
        private String fileUrl;
        
        @NotNull(message = "文件大小不能为空")
        @Min(value = 1, message = "文件大小必须大于0")
        private Long fileSize;
        
        @Size(max = 255, message = "文件名长度不能超过255个字符")
        private String fileName;
        
        public String getFileUrl() {
            return fileUrl;
        }
        
        public void setFileUrl(String fileUrl) {
            this.fileUrl = fileUrl;
        }
        
        public Long getFileSize() {
            return fileSize;
        }
        
        public void setFileSize(Long fileSize) {
            this.fileSize = fileSize;
        }
        
        public String getFileName() {
            return fileName;
        }
        
        public void setFileName(String fileName) {
            this.fileName = fileName;
        }
    }
    
    /**
     * 添加语音条目请求DTO
     */
    public static class AddAudioEntryRequest {
        @NotBlank(message = "文件URL不能为空")
        @Size(max = 500, message = "文件URL长度不能超过500个字符")
        private String fileUrl;
        
        @NotNull(message = "文件大小不能为空")
        @Min(value = 1, message = "文件大小必须大于0")
        private Long fileSize;
        
        @NotNull(message = "音频时长不能为空")
        @Min(value = 1, message = "音频时长必须大于0秒")
        private Integer duration;
        
        @Size(max = 255, message = "文件名长度不能超过255个字符")
        private String fileName;
        
        public String getFileUrl() {
            return fileUrl;
        }
        
        public void setFileUrl(String fileUrl) {
            this.fileUrl = fileUrl;
        }
        
        public Long getFileSize() {
            return fileSize;
        }
        
        public void setFileSize(Long fileSize) {
            this.fileSize = fileSize;
        }
        
        public Integer getDuration() {
            return duration;
        }
        
        public void setDuration(Integer duration) {
            this.duration = duration;
        }
        
        public String getFileName() {
            return fileName;
        }
        
        public void setFileName(String fileName) {
            this.fileName = fileName;
        }
    }
}